package panel.control;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.Box;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.border.EmptyBorder;

import panel.canvas.CanvasObserver;
import panel.canvas.CanvasPanel;
import panel.event.LightSelectedListener;
import panel.event.PropertyChangedListener;
import shape.Light;
import shape.Shape;
import window.Axis;
import window.Hue;
import camera.Camera;


public class ControlPanel extends JPanel implements CanvasObserver {
	private List<JPanel>	panelList;
	private ActionListener	actionControl;
	private PropertyChangedListener propertyControl;
	private LightSelectedListener lightControl;
	
	private ValuePanel		positionPanel;
	private ValuePanel		rotationPanel;
	private ValuePanel		sizePanel;
	private ValuePanel		colorPanel;
	private ValuePanel		cameraPanel;
	private GeneratePanel	generatePanel;
	private LightPanel		lightPanel;
	
	public ControlPanel( ActionListener actionControl, PropertyChangedListener propertyControl,
			LightSelectedListener lightControl ) {
		this.actionControl = actionControl;
		this.propertyControl = propertyControl;
		this.lightControl = lightControl;
		
		createPanels();
		createLayout();
	}

	public void createPanels() {
		panelList = new ArrayList<JPanel>(5);
		
		// Create value panels
		
		positionPanel	= new ValuePanel("Position", propertyControl);
		rotationPanel	= new ValuePanel("Rotation", propertyControl);
		sizePanel		= new ValuePanel("Size", propertyControl);
		colorPanel		= new ValuePanel("Color", propertyControl);
		cameraPanel		= new ValuePanel("Camera", propertyControl);
		generatePanel 	= new GeneratePanel( actionControl );
		lightPanel		= new LightPanel( actionControl, lightControl );
		
		// Initialize shape panels
		
		positionPanel.addField( Axis.NAME, Shape.PROPERTY_POSITION, Axis.ALL );
		rotationPanel.addField( Axis.NAME, Shape.PROPERTY_ROTATION, Axis.ALL, 1.0 );
		sizePanel.addField( Axis.NAME, Shape.PROPERTY_SIZE, Axis.ALL );
		colorPanel.addField( Hue.NAME, Shape.PROPERTY_COLOR, Hue.ALL );
		
		// Initialize camera panel
		
		for (int axis: Axis.ALL) {
			cameraPanel.addField("Eye " + Axis.NAME[axis], Camera.PROPERTY_EYE, axis);
		}
		
		cameraPanel.addSpace();
		
		for (int axis: Axis.ALL) {
			cameraPanel.addField("Target " + Axis.NAME[axis], Camera.PROPERTY_TARGET, axis);
		}
		
		cameraPanel.addSpace();
		
		// NOTE: 'index' is irrelevant for these properties
		cameraPanel.addField("Distance", Camera.PROPERTY_DISTANCE, 0);
		cameraPanel.addField("Yaw", Camera.PROPERTY_YAW, 0, 1.0);
		cameraPanel.addField("Pitch", Camera.PROPERTY_PITCH, 0, 1.0);
		
		// Add all panels to this panel
		
		panelList.add(positionPanel);
		panelList.add(rotationPanel);
		panelList.add(sizePanel);
		panelList.add(colorPanel);
		panelList.add(cameraPanel);
		panelList.add(generatePanel);
		panelList.add(lightPanel);
	}
	
	public void createLayout() {
		GridBagConstraints c = new GridBagConstraints();
		
		setLayout( new GridBagLayout() );
		setBackground( Color.lightGray );
		setBorder( new EmptyBorder(0, 5, 0, 5) );

		c.fill		= GridBagConstraints.BOTH;
		c.anchor	= GridBagConstraints.NORTH;
		c.gridx		= 0;
		c.gridy		= GridBagConstraints.RELATIVE;
		c.weighty	= 0.0;
		c.weightx	= 1.0;
		c.insets	= new Insets(5, 0, 0, 0);
		
		for (JPanel p: panelList) {
			add( p, c );
			add( new JSeparator(JSeparator.HORIZONTAL), c );
		}
		
		c.weighty = 1.0;
		add(Box.createVerticalGlue(), c);
		
	}
	
	/* ----------------------------------------------------
	 * Property setters (based on world elements)
	 */
	
	public void setPropertyData( Shape shape ) {
		positionPanel.setData(shape);
		rotationPanel.setData(shape);
		sizePanel.setData(shape);
		colorPanel.setData(shape);
	}
	
	public void setPropertiesEnabled( boolean buttons, boolean text ) {
		positionPanel.setEnabled(buttons, text);
		rotationPanel.setEnabled(buttons, text);
		sizePanel.setEnabled(buttons, text);
		colorPanel.setEnabled(buttons, text);
	}
	
	public void setPropertiesEnabled( boolean enabled ) {
		setPropertiesEnabled(enabled, enabled);
	}
	
	public void setCameraData( Camera camera ) {
		cameraPanel.setData(camera);
	}
	
	/* ----------------------------------------------------
	 * Getter functions
	 */
	
	public int getSelectedShapeType() {
		return generatePanel.getSelectedShapeType();
	}
	
	public Light[] getSelectedLights() {
		return lightPanel.getSelectedLights();
	}
	
	/* ----------------------------------------------------
	 * Canvas observer update function
	 */
	
	public void update(CanvasPanel canvas) {
		Shape[] selectedShapeList = canvas.getSelectedShapes();
		
		if (selectedShapeList.length == 0) {
			setPropertiesEnabled(false);
		}
		else if (selectedShapeList.length == 1) {
			setPropertiesEnabled(true);
			setPropertyData( selectedShapeList[0] );
		}
		else {
			setPropertiesEnabled(true, false);
		}
		
		setCameraData( canvas.getCamera() );
		lightPanel.updateLights( canvas.getLights() );
	}
}
